home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.mactech.com 2010
/
ftp.mactech.com.tar
/
ftp.mactech.com
/
macintosh-c
/
macc-carbon-demos-nonbinhex.sit
/
macc-carbon-demos-nonbinhex
/
chap23-demo-classic events
/
StartAndTrackDrag.c
< prev
next >
Wrap
Text File
|
2001-05-31
|
11KB
|
384 lines
// *******************************************************************************************
// StartAndTrackDrag.c
// *******************************************************************************************
// ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
#include "Drag.h"
// …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
Boolean gCursorInContent, gCanAcceptItems, gCaretShowFlag;
SInt16 gInsertPosition, gLastOffset, gCaretOffset;
UInt32 gSystemCaretTime, gCaretStartTime;
extern Boolean gRunningOnX;
// ******************************************************************************* doStartDrag
OSErr doStartDrag(EventRecord *eventStrucPtr,RgnHandle hiliteRgnHdl,TEHandle textEditStrucHdl)
{
OSErr osError;
DragReference dragRef;
Rect originalHiliteRect, zeroedHiliteRect;
RgnHandle maskRgnHdl;
Point offsetPoint;
QDErr qdError;
CGrafPtr savedPortPtr;
GDHandle saveDeviceHdl;
GWorldPtr dragGWorldPtr = NULL;
PixMapHandle dragPixMapHdl, windPixMapHdl;
RgnHandle dragRgnHdl, tempRgnHdl;
// ………………………………………………………………………………………………………………………………………………………………………………………………… create new drag
if(osError = NewDrag(&dragRef))
return osError;
// ………………………………………………………………………………………………………………………………………………………………………………………… add 'TEXT' flavour
osError = AddDragItemFlavor(dragRef,1,'TEXT',
(*(*textEditStrucHdl)->hText) + (*textEditStrucHdl)->selStart,
(*textEditStrucHdl)->selEnd - (*textEditStrucHdl)->selStart,0);
// ……………………………………………………………………………………………… get and set drag image for translucent drag and drop
if(!gRunningOnX)
{
maskRgnHdl = dragRgnHdl = tempRgnHdl = NULL;
GetRegionBounds(hiliteRgnHdl,&originalHiliteRect);
zeroedHiliteRect = originalHiliteRect;
OffsetRect(&zeroedHiliteRect,-originalHiliteRect.left,-originalHiliteRect.top);
GetGWorld(&savedPortPtr,&saveDeviceHdl);
qdError = NewGWorld(&dragGWorldPtr,8,&zeroedHiliteRect,NULL,NULL,0);
if(dragGWorldPtr != NULL && qdError == noErr)
{
SetGWorld(dragGWorldPtr,NULL);
EraseRect(&zeroedHiliteRect);
dragPixMapHdl = GetGWorldPixMap(dragGWorldPtr);
LockPixels(dragPixMapHdl);
windPixMapHdl = GetGWorldPixMap(savedPortPtr);
CopyBits((BitMap *) *windPixMapHdl,(BitMap *) *dragPixMapHdl,
&originalHiliteRect,&zeroedHiliteRect,srcCopy,NULL);
UnlockPixels(dragPixMapHdl);
SetGWorld(savedPortPtr,saveDeviceHdl);
maskRgnHdl = NewRgn();
if(maskRgnHdl != NULL)
{
CopyRgn(hiliteRgnHdl,maskRgnHdl);
OffsetRgn(maskRgnHdl,-originalHiliteRect.left,-originalHiliteRect.top);
SetPt(&offsetPoint,originalHiliteRect.left,originalHiliteRect.top);
LocalToGlobal(&offsetPoint);
SetDragImage(dragRef,dragPixMapHdl,maskRgnHdl,offsetPoint,kDragStandardTranslucency);
}
}
}
// ………………………………………………………………………………………………………………………………………………………………………………………………… get drag region
dragRgnHdl = NewRgn();
if(dragRgnHdl == NULL)
return MemError();
CopyRgn(hiliteRgnHdl,dragRgnHdl);
SetPt(&offsetPoint,0,0);
LocalToGlobal(&offsetPoint);
OffsetRgn(dragRgnHdl,offsetPoint.h,offsetPoint.v);
tempRgnHdl = NewRgn();
if(tempRgnHdl == NULL)
return MemError();
CopyRgn(dragRgnHdl,tempRgnHdl);
InsetRgn(tempRgnHdl,1,1);
DiffRgn(dragRgnHdl,tempRgnHdl,dragRgnHdl);
DisposeRgn(tempRgnHdl);
// ……………………………………………………………………………………………………………………………………………………………………………………………… perform the drag
osError = TrackDrag(dragRef,eventStrucPtr,dragRgnHdl);
if(osError != noErr && osError != userCanceledErr)
return osError;
if(dragRef) DisposeDrag(dragRef);
if(maskRgnHdl) DisposeRgn(maskRgnHdl);
if(dragGWorldPtr) DisposeGWorld(dragGWorldPtr);
if(dragRgnHdl) DisposeRgn(dragRgnHdl);
if(tempRgnHdl) DisposeRgn(tempRgnHdl);
return noErr;
}
// *********************************************************************** dragTrackingHandler
OSErr dragTrackingHandler(DragTrackingMessage trackingMessage,WindowRef windowRef,
void *handlerRefCon,DragRef dragRef)
{
docStructurePointer docStrucPtr;
DragAttributes dragAttributes;
UInt32 theTime;
UInt16 numberOfDragItems, index;
ItemReference itemRef;
OSErr result;
FlavorFlags flavorFlags;
Point mousePt, localMousePt;
RgnHandle windowHiliteRgn;
Rect correctedViewRect;
SInt16 theOffset;
if((trackingMessage != kDragTrackingEnterHandler) && !gCanAcceptItems)
return noErr;
docStrucPtr = (docStructurePointer) handlerRefCon;
GetDragAttributes(dragRef,&dragAttributes);
gSystemCaretTime = GetCaretTime();
theTime = TickCount();
switch(trackingMessage)
{
// ………………………………………………………………………………………………………………………………………………………………………………………………… enter handler
case kDragTrackingEnterHandler:
gCanAcceptItems = true;
CountDragItems(dragRef,&numberOfDragItems);
for(index=1;index <= numberOfDragItems;index++)
{
GetDragItemReferenceNumber(dragRef,index,&itemRef);
result = GetFlavorFlags(dragRef,itemRef,'TEXT',&flavorFlags);
if(result != noErr)
{
gCanAcceptItems = false;
break;
}
}
break;
// ……………………………………………………………………………………………………………………………………………………………………………………………… enter window
case kDragTrackingEnterWindow:
gCaretStartTime = theTime;
gCaretOffset = gLastOffset = -1;
gCaretShowFlag = true;
gCursorInContent = false;
break;
// …………………………………………………………………………………………………………………………………………………………………………………………………………… in window
case kDragTrackingInWindow:
GetDragMouse(dragRef,&mousePt,NULL);
localMousePt = mousePt;
GlobalToLocal(&localMousePt);
if(dragAttributes & kDragHasLeftSenderWindow)
{
if(PtInRect(localMousePt,&(**(docStrucPtr->textEditStrucHdl)).viewRect))
{
if(!gCursorInContent)
{
windowHiliteRgn = NewRgn();
correctedViewRect = (**(docStrucPtr->textEditStrucHdl)).viewRect;
InsetRect(&correctedViewRect,-2,-2);
RectRgn(windowHiliteRgn,&correctedViewRect);
ShowDragHilite(dragRef,windowHiliteRgn,true);
DisposeRgn(windowHiliteRgn);
}
gCursorInContent = true;
}
else
{
if(gCursorInContent)
HideDragHilite(dragRef);
gCursorInContent = false;
}
}
// … … … … … … … … … … … … start caret drawing stuff, first get the offset into the text
theOffset = doGetOffset(mousePt,docStrucPtr->textEditStrucHdl);
// … … … … … … … … … … … … … … … if in sender window, defeat caret drawing in selection
if(dragAttributes & kDragInsideSenderWindow)
{
if((theOffset >= (*(docStrucPtr->textEditStrucHdl))->selStart) &&
(theOffset <= (*(docStrucPtr->textEditStrucHdl))->selEnd))
{
theOffset = -1;
}
}
// … … … … … … … … … … … … … … save the offset to a global for use by dragReceiveHandler
gInsertPosition = theOffset;
// … … … … … … … … … … … … … … … … if offset has changed, reset the caret flashing timer
if(theOffset != gLastOffset)
{
gCaretStartTime = theTime;
gCaretShowFlag = true;
}
gLastOffset = theOffset;
// … … … … if caret-flashing interval has elapsed, toggle caret "show" flag, reset timer
if(theTime - gCaretStartTime > gSystemCaretTime)
{
gCaretShowFlag = !gCaretShowFlag;
gCaretStartTime = theTime;
}
// … … … … … … … … … … if caret "show" flag is off, set variable to defeat caret drawing
if(!gCaretShowFlag)
theOffset = -1;
// … … … … if offset has changed, erase previous caret, draw new caret at current offset
if(theOffset != gCaretOffset)
{
// … … … … … … … if first pass this window, don't erase, otherwise erase at old offset
if(gCaretOffset != -1)
doDrawCaret(gCaretOffset,docStrucPtr->textEditStrucHdl);
// … … … … … … … … … … … … … if "show" flag says show, draw caret at current offset
if(theOffset != -1)
doDrawCaret(theOffset,docStrucPtr->textEditStrucHdl);
}
gCaretOffset = theOffset;
break;
// …………………………………………………………………………………………………………………………………………………………………………………………………… leave window
case kDragTrackingLeaveWindow:
if(gCaretOffset != -1)
{
doDrawCaret(gCaretOffset,docStrucPtr->textEditStrucHdl);
gCaretOffset = -1;
}
if(gCursorInContent && dragAttributes & kDragHasLeftSenderWindow)
HideDragHilite(dragRef);
break;
// ………………………………………………………………………………………………………………………………………………………………………………………………… leave handler
case kDragTrackingLeaveHandler:
break;
}
return noErr;
}
// ******************************************************************************* doGetOffset
SInt16 doGetOffset(Point mousePt,TEHandle textEditStrucHdl)
{
WindowRef windowRef;
SInt16 theOffset;
Point thePoint;
theOffset = -1;
if(FindWindow(mousePt,&windowRef) == inContent)
{
SetPortWindowPort(windowRef);
GlobalToLocal(&mousePt);
if(PtInRect(mousePt,&((*textEditStrucHdl)->viewRect)))
{
theOffset = TEGetOffset(mousePt,textEditStrucHdl);
thePoint = TEGetPoint(theOffset - 1,textEditStrucHdl);
if((theOffset) &&
(doIsOffsetAtLineStart(theOffset,textEditStrucHdl)) &&
((*(*textEditStrucHdl)->hText)[theOffset - 1] != 0x0D) &&
(thePoint.h < mousePt.h))
{
theOffset--;
}
}
}
return theOffset;
}
// ********************************************************************* doIsOffsetAtLineStart
SInt16 doIsOffsetAtLineStart(SInt16 offset,TEHandle textEditStrucHdl)
{
SInt16 line = 0;
if((*textEditStrucHdl)->teLength == 0)
return(true);
if(offset >= (*textEditStrucHdl)->teLength)
return((*((*textEditStrucHdl)->hText))[(*textEditStrucHdl)->teLength - 1] == 0x0D);
while((*textEditStrucHdl)->lineStarts[line] < offset)
line++;
return ((*textEditStrucHdl)->lineStarts[line] == offset);
}
// ******************************************************************************* doDrawCaret
void doDrawCaret(SInt16 theOffset,TEHandle textEditStrucHdl)
{
Point thePoint;
SInt16 theLine, lineHeight;
thePoint = TEGetPoint(theOffset,textEditStrucHdl);
theLine = doGetLine(theOffset,textEditStrucHdl);
if((theOffset == (*textEditStrucHdl)->teLength) &&
(*((*textEditStrucHdl)->hText))[(*textEditStrucHdl)->teLength - 1] == 0x0D)
{
thePoint.v += TEGetHeight(theLine,theLine,textEditStrucHdl);
}
PenMode(patXor);
lineHeight = TEGetHeight(theLine,theLine,textEditStrucHdl);
MoveTo(thePoint.h - 1,thePoint.v - 1);
Line(0,1 - lineHeight);
PenNormal();
}
// ********************************************************************************* doGetLine
SInt16 doGetLine(SInt16 theOffset,TEHandle textEditStrucHdl)
{
SInt16 theLine = 0;
if(theOffset > (*textEditStrucHdl)->teLength)
return ((*textEditStrucHdl)->nLines);
while((*textEditStrucHdl)->lineStarts[theLine] < theOffset)
theLine++;
return theLine;
}
// *******************************************************************************************